package com.siyoumi.app.modules.app_book.web;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.siyoumi.annotation.RequestLimit;
import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.app_book.entity.EnumBookSpuFoodType;
import com.siyoumi.app.modules.app_book.entity.EnumBookSpuToilet;
import com.siyoumi.app.modules.app_book.entity.EnumBookSpuToiletType;
import com.siyoumi.app.modules.app_book.entity.EnumBookSpuViewType;
import com.siyoumi.app.modules.app_book.service.*;
import com.siyoumi.app.modules.app_book.vo.*;
import com.siyoumi.app.modules.fun.service.SvcFun;
import com.siyoumi.app.modules.fun.vo.VaFunAdd;
import com.siyoumi.app.service.*;
import com.siyoumi.app.sys.service.SvcSysUv;
import com.siyoumi.app.sys.vo.VoUvSave;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XEnumBase;
import com.siyoumi.component.http.InputData;
import com.siyoumi.controller.WxAppApiController;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/wxapp/app_book/api")
public class ApiAppBook
        extends WxAppApiController {
    /**
     * 初始化
     */
    @GetMapping("init")
    public XReturn init() {
        SysAbc setting = SvcBookSetting.getBean().getSetting();
        XValidator.isNull(setting, "未初始化");

        getR().put("banner", SysItemService.getBean().getItemDataByIdSrc(setting.getAbc_str_00())); //轮播图
        getR().put("menu", SysItemService.getBean().getItemDataByIdSrc(setting.getAbc_str_01())); //首页菜单
        getR().put("hot_city", SysItemService.getBean().getItemDataByIdSrc(setting.getAbc_str_02())); //热门城市
        getR().put("my", SysItemService.getBean().getItemDataByIdSrc(setting.getAbc_str_03())); //我的

        return getR();
    }

    /**
     * 项列表
     */
    @GetMapping("item_list")
    public XReturn itemList() {
        String type = input("type");
        XValidator.isNullOrEmpty(type, "miss type");
        InputData inputData = InputData.fromRequest();

        String[] select = {
                "bitem_id",
                "bitem_pid",
                "bitem_name",
                "bitem_pic",
                "bitem_str_00",
        };
        JoinWrapperPlus<BookItem> query = SvcBookItem.getBean().listQuery(inputData);
        query.select(select);
        List<Map<String, Object>> list = SvcBookItem.getApp().getMaps(query);
        getR().put("list", list);

        return getR();
    }

    public String[] storeSelect() {
        return new String[]{
                "bstore_id",
                "bstore_title",
                "bstore_group_id",
                "bstore_banner",
                "bstore_tag",
                "bstore_province",
                "bstore_city",
                "bstore_district",
                "bstore_day1_price",
                "bset_name",
                "bset_day_price",
        };
    }

    /**
     * 热门基地列表
     */
    @GetMapping("store_list_hot")
    public XReturn storeListHot() {
        InputData inputData = InputData.getIns();
        inputData.put("type", "hot");

        String[] select = storeSelect();
        JoinWrapperPlus<BookItem> query = SvcBookItem.getBean().listQuery(inputData);
        query.join(BookStore.table(), BookStore.tableKey(), "bitem_pid");
        query.leftJoin(BookSet.table(), BookSet.tableKey(), "bstore_set_id");
        query.select(select);
        List<Map<String, Object>> list = SvcBookItem.getApp().getMaps(query);
        getR().put("list", list);
        return getR();
    }

    /**
     * 基地列表
     */
    @GetMapping("store_list")
    public XReturn storeList() {
        InputData inputData = InputData.fromRequest();
        boolean getCount = "1".equals(inputData.input("get_count")); //只需要总数


        String[] select = storeSelect();
        JoinWrapperPlus<BookStore> query = SvcBookStore.getBean().listQuery(inputData);
        query.leftJoin(BookSet.table(), BookSet.tableKey(), "bstore_set_id");
        query.eq("bstore_enable", 1);
        if (!getCount) {
            query.select(select);
            List<Map<String, Object>> list = SvcBookStore.getApp().getMaps(query);
            //
            List<String> storeIds = list.stream().map(item -> (String) item.get("bstore_id")).collect(Collectors.toList());
            //收藏数据
            List<String> collectIds = new ArrayList<>();
            if (isLogin()) {
                collectIds = SvcSysUv.getBean().getTypeIds(storeIds, "store_collect", getUid());
            }
            Map<String, List<String>> mapCity = new HashMap<>();
            for (Map<String, Object> item : list) {
                BookStore entity = XBean.fromMap(item, BookStore.class);
                //收藏
                item.put("is_collect", collectIds.contains(entity.getKey()));

                //省份城市处理
                List<String> listCity = mapCity.get(entity.getBstore_province());
                if (listCity == null) {
                    listCity = new ArrayList<>();
                    mapCity.put(entity.getBstore_province(), listCity);
                }
                if (!listCity.contains(entity.getBstore_city())) {
                    listCity.add(entity.getBstore_city());
                    mapCity.put(entity.getBstore_province(), listCity);
                }
            }

            getR().put("list", list);
            getR().put("city", mapCity);
        } else {
            Long count = SvcBookStore.getApp().count(query);
            getR().put("total", count);
        }

        return getR();
    }

    /**
     * 基地详情
     */
    @GetMapping("store_info")
    public XReturn storeInfo() {
        String storeId = input("store_id");
        XValidator.isNullOrEmpty(storeId, "miss store_id");

        BookStore entityStore = SvcBookStore.getApp().getEntity(storeId);
        XValidator.isNull(entityStore, "store_id error");

        BookStoreTxt entityStoreTxt = BookStoreTxtService.getBean().loadEntity(entityStore.getKey());
        VaBookStoreTxtInfo storeTxtInfo = XJson.parseObject(entityStoreTxt.getBstoret_info(), VaBookStoreTxtInfo.class);

        //基地
        Map<String, Object> mapStore = XBean.toMap(entityStore, new String[]{
                "bstore_id",
                "bstore_title",
                "bstore_banner",
                "bstore_tag",
                "bstore_province",
                "bstore_city",
                "bstore_district",
                "bstore_address",
                "bstore_point_x",
                "bstore_point_y",
        });
        mapStore.put("txt_info", storeTxtInfo);
        Boolean isCollect = false; //收藏状态
        if (isLogin()) {
            isCollect = SvcSysUv.getBean().exists("store_collect", entityStore.getKey(), getUid());
        }
        mapStore.put("is_collect", isCollect);
        getR().setData("store", mapStore);

        //房源列表
        List<Map<String, Object>> listSpu = SvcBookSpu.getBean().apiSpuList(InputData.fromRequest());
        getR().put("list_spu", listSpu);
        //套餐
        BookSet entitySet = SvcBookSet.getBean().getFirst(storeId);
        Map<String, Object> mapSet = XBean.toMap(entitySet, new String[]{
                "bset_id",
                "bset_name",
                "bset_day_price",
        });
        getR().put("set", mapSet);

        return getR();
    }

    /**
     * 用户收藏
     * 基地，房间
     */
    @PostMapping("collect")
    public XReturn collect(@Validated VoUvSave vo, BindingResult result) {
        XValidator.isNullOrEmpty(vo.getType_id(), "miss type_id");
        List<String> types = List.of("store_collect", "spu_collect");
        if (!types.contains(vo.getType())) {
            result.addError(XValidator.getErr("type", "请输入指定值：" + types));
        }
        //
        XValidator.getResult(result, true, true);

        vo.setApp_id("app_book");
        vo.setUid(getUid());
        return SvcSysUv.getBean().save(vo);
    }

    /**
     * 房源列表
     */
    @GetMapping("spu_list")
    public XReturn spuList() {
        InputData inputData = InputData.fromRequest();

        List<Map<String, Object>> listSpu = SvcBookSpu.getBean().apiSpuList(inputData);

        getR().put("list", listSpu);

        return getR();
    }

    /**
     * 房间详情
     */
    @GetMapping("spu_info")
    public XReturn spuInfo() {
        String spuId = input("spu_id");
        XValidator.isNullOrEmpty(spuId, "miss spu_id");

        BookSpu entitySpu = SvcBookSpu.getApp().getEntity(spuId);
        XValidator.isNull(entitySpu, "spu_id error");
        //房源显示
        Map<String, Object> mapSpu = XBean.toMap(entitySpu);

        BookSpuTxt entitySpuTxt = BookSpuTxtService.getBean().getEntity(entitySpu.getKey());
        VaBookSpuTxt spuTxt = XJson.parseObject(entitySpuTxt.getBsput_txt_00(), VaBookSpuTxt.class);
        mapSpu.put("txt_info", spuTxt);
        //枚举
        EnumBookSpuFoodType enumFoodType = XEnumBase.of(EnumBookSpuFoodType.class); //做饭
        EnumBookSpuToilet enumToilet = XEnumBase.of(EnumBookSpuToilet.class); //厕所
        EnumBookSpuToiletType enumToiletType = XEnumBase.of(EnumBookSpuToiletType.class); //厕所类型
        EnumBookSpuViewType enumViewType = XEnumBase.of(EnumBookSpuViewType.class); //景色
        mapSpu.put("food_type", enumFoodType.get(entitySpu.getBspu_food_type()));
        mapSpu.put("toilet", enumToilet.get(entitySpu.getBspu_toilet()));
        mapSpu.put("toilet_type", enumToiletType.get(entitySpu.getBspu_toilet_type()));
        mapSpu.put("view_type", enumViewType.get(entitySpu.getBspu_view_type()));
        //
        getR().put("spu", mapSpu);
        //房间设施
        List<Map<String, Object>> listDevice = SvcBookItem.getBean().getList("device", null);
        getR().put("device", listDevice);
        //sku
        List<Map<String, Object>> listSku = SvcBookSku.getBean().getList(List.of(entitySpu.getKey()));
        getR().put("list_sku", listSku);

        //set list
        List<Map<String, Object>> listSet = SvcBookSet.getBean().getList(entitySpu.getBspu_store_id(), entitySpu.getKey());
        getR().put("list_set", listSet);

        //商家
        BookStoreTxt entityStoreTxt = BookStoreTxtService.getBean().loadEntity(entitySpu.getBspu_store_id());
        VaBookStoreTxtInfo storeTxtInfo = XJson.parseObject(entityStoreTxt.getBstoret_info(), VaBookStoreTxtInfo.class);
        //
        BookStore entityStore = SvcBookStore.getApp().getEntity(entitySpu.getBspu_store_id());
        //
        Map<String, Object> mapStore = new HashMap<>();
        mapStore.put("txt_info", storeTxtInfo);
        if (entityStore != null) {
            mapStore.put("bstore_deposit_enable", entityStore.getBstore_deposit_enable());
            mapStore.put("bstore_deposit_rate", entityStore.getBstore_deposit_rate());
            mapStore.put("bstore_app_rate", entityStore.getBstore_app_rate());
            mapStore.put("bstore_refund_rule", entityStore.getBstore_refund_rule());
        }
        getR().put("store", mapStore);

        return getR();
    }

    /**
     * 房间日期列表（加价&库存）
     */
    @GetMapping("spu_day_list")
    public XReturn spuDayList() {
        String spuId = input("spu_id");
        String setId = input("set_id");
        String skuId = input("sku_id");
        String dateBegin = input("date_begin");
        String dateEnd = input("date_end");
        XValidator.isNullOrEmpty(spuId, "miss spu_id");
        XValidator.isNullOrEmpty(setId, "miss set_id");
        XValidator.isNullOrEmpty(dateBegin, "miss date_begin");
        XValidator.isNullOrEmpty(dateEnd, "miss date_end");

        BookSpu entitySpu = SvcBookSpu.getApp().getEntity(spuId);
        XValidator.isNull(entitySpu, "spu_id error");

        LocalDateTime b = XDate.parse(dateBegin);
        LocalDateTime e = XDate.parse(dateEnd);
        //
        //List<LocalDateTime> dateList = XDate.getDateList(b, e, null);
        List<SpuDayData> listDay = SvcBookSpu.getBean().listDay(entitySpu, b, e);
        //套餐加价列表
        {
            JoinWrapperPlus<BookSetDay> query = SvcBookSet.getBean().listDayQuery(setId);
            query.between("bsday_date", dateBegin, dateEnd);
            query.select("bsday_id", "bsday_date", "bsday_add_price");
            List<Map<String, Object>> listSet = BookSetDayService.getBean().getMaps(query);
            getR().put("list_set", listSet);
        }
        //sku价格列表
        if (XStr.hasAnyText(skuId)) {
            BookSku entitySku = SvcBookSku.getApp().getEntity(skuId);
            XValidator.isNull(entitySku, "sku_id error");
            //
            List<SkuDayData> listDaySku = SvcBookSku.getBean().listDay(entitySku, b, e);
            getR().put("list_day_sku", listDaySku);
        }
        getR().put("list", listDay);

        return getR();
    }

    /**
     * sku每日价格
     */
    @GetMapping("sku_day_list")
    public XReturn skuDayList() {
        String skuId = input("sku_id");
        String dateBegin = input("date_begin");
        String dateEnd = input("date_end");
        XValidator.isNullOrEmpty(skuId, "miss spu_id");
        XValidator.isNullOrEmpty(dateBegin, "miss date_begin");
        XValidator.isNullOrEmpty(dateEnd, "miss date_end");

        LocalDateTime b = XDate.parse(dateBegin);
        LocalDateTime e = XDate.parse(dateEnd);

        BookSku entitySku = SvcBookSku.getApp().getEntity(skuId);
        XValidator.isNull(entitySku, "sku_id error");
        //
        List<SkuDayData> listDaySku = SvcBookSku.getBean().listDay(entitySku, b, e);
        //包房总价
        BigDecimal priceTotalPrivate = listDaySku.stream()
                .map(item -> item.getDay_price_private())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //拼房总价
        BigDecimal priceTotal = listDaySku.stream()
                .map(item -> item.getDay_price())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        getR().put("list_day_sku", listDaySku);
        getR().put("price_total", priceTotal);
        getR().put("price_total_private", priceTotalPrivate);

        return getR();
    }

    /**
     * 下单
     */
    @RequestLimit(key = RequestLimitAppBook.class, second = 2)
    @PostMapping("order")
    public XReturn order(@Validated VoBookOrder vo, BindingResult result) {
        //
        XValidator.getResult(result, true, true);
        //
        if (vo.getDate_begin().isBefore(XDate.today())) {
            result.addError(XValidator.getErr("date_begin", "开始日期要大于或者等于当天"));
        }
        XValidator.getResult(result, true, true);
        //
        getUid();
        vo.setContinue_order(false);
        //
        XReturn r = SvcBookOrder.getBean().order(vo);
        if (r.err()) {
            //LogPipeLine.getTl().saveDb("order", XHttpContext.getX());
        }
        return r;
    }

    /**
     * 第2次下单
     *
     * @param vo
     * @param result
     */
    @PostMapping("order01")
    public XReturn order01(@Validated VoBookOrder01 vo, BindingResult result) {
        //
        XValidator.getResult(result, true);
        //
        getUid();
        //
        return SvcBookOrder.getBean().order01(vo);
    }

    /**
     * 订单详情
     */
    @GetMapping("order_info")
    public XReturn orderInfo() {
        String orderId = input("order_id");
        XValidator.isNullOrEmpty(orderId, "miss order_id");

        String[] select = {
                "border_id",
                "border_user_name",
                "border_user_phone",
                "border_date_begin",
                "border_date_end",
                "border_date_end_final",
                "border_uid",
                "border_day",
                "border_create_date",
                "border_spu_count",
                "border_sku_user_count",
                "border_set_user_count",
                "border_set_name",
                "border_set_id",
                "border_set_day_price",
                "border_price_down_fun",
                "border_price_final",
                "border_deposit",
                "border_deposit_price",
                "border_price_final",
                "border_price_pay",
                "border_price_pay_total",
                "border_desc",
                "border_status",
                "border_refund",
                "border_continue",
                "border_spu_id",
                "border_spu_pay",
                "bspu_name",
                "bspu_logo",
                "bstore_title",
                "bstore_refund_rule",
                "order_id",
                "order_pay_ok",
                "order_pay_expire_date",
        };
        JoinWrapperPlus<BookOrder> query = SvcBookOrder.getBean().listQuery();
        query.join(BookSpu.table(), BookSpu.tableKey(), "border_spu_id");
        query.join(BookStore.table(), BookStore.tableKey(), "border_store_id");
        query.join(SysOrder.table(), SysOrder.tableKey(), "border_id");
        query.eq("border_id", orderId);
        query.select(select);
        Map<String, Object> mapOrder = SvcBookOrder.getApp().firstMap(query);
        XValidator.isNull(mapOrder, "订单号异常");
        //
        BookOrder entity = XBean.fromMap(mapOrder, BookOrder.class);
        //
        mapOrder.put("border_date_end", entity.getBorder_date_end_final().plusDays(1)); //退房日期要+1
        BookOrder entityOrder = XBean.fromMap(mapOrder, BookOrder.class);
        mapOrder.put("border_user_phone", XStr.markStarPhone(entityOrder.getBorder_user_phone())); //手机号加星

        SysOrder entitySysOrder = XBean.fromMap(mapOrder, SysOrder.class);
        mapOrder.put("expire_seconds", entitySysOrder.expireSeconds()); //支付过期时间
        //退款手续费
        List<VoBookOrderRefundRule> refundRule = SvcBookStore.getBean().getRefundRule((String) mapOrder.get("bstore_refund_rule"));
        BigDecimal refundRate = SvcBookStore.getBean().getRefundRate(refundRule, entityOrder.getBorder_date_begin());
        mapOrder.put("refund_rate", refundRate);
        getR().put("order", mapOrder);
        //退款信息
        BookRefundOrder entityRefund = SvcBookOrder.getBean().getEntityRefund(entityOrder.getKey());
        Map<String, Object> mapRefund = XBean.toMap(entityRefund, new String[]{
                "brefo_id",
                "brefo_apply_price",
                "brefo_price_down",
                "brefo_audit_status",
                "brefo_audit_status_date",
                "brefo_audit_desc",
                "brefo_refund_id00",
                "brefo_refund_price",
                "brefo_refund_handle",
                "brefo_refund_handle_date",
                "brefo_refund_errmsg",
        });

        getR().put("refund", mapRefund);

        return getR();
    }

    /**
     * 订单列表
     */
    @GetMapping("order_list")
    public XReturn orderList() {
        InputData inputData = InputData.fromRequest();

        String[] select = {
                "border_id",
                "border_pay01_order_id",
                "border_date_begin",
                "border_date_end",
                "border_date_end_final",
                "border_day",
                "border_sku_user_count",
                "border_sku_user_count",
                "border_set_name",
                "border_create_date",
                "border_spu_count",
                "border_set_day_price",
                "border_set_user_count",
                "border_deposit",
                "border_deposit_price",
                "border_price_down_fun",
                "border_price_final",
                "border_price_pay",
                "border_price_pay_total",
                "border_desc",
                "border_status",
                "border_refund",
                "border_continue",
                "border_continue_day_total",
                "border_spu_id",
                "border_spu_pay",
                "bspu_name",
                "bspu_logo",
                "bstore_title",
        };
        JoinWrapperPlus<BookOrder> query = SvcBookOrder.getBean().listQuery(inputData);
        query.join(BookSpu.table(), BookSpu.tableKey(), "border_spu_id");
        query.join(BookStore.table(), BookStore.tableKey(), "border_store_id");
        query.eq("border_uid", getUid())
                .eq("border_enable", 1);
        query.select(select);
        query.orderByDesc("border_id");

        IPage<BookOrder> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), false);
        //list
        IPage<Map<String, Object>> pageData = SvcBookOrder.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        for (Map<String, Object> item : list) {
            BookOrder entity = XBean.fromMap(item, BookOrder.class);
            item.put("border_date_end", entity.getBorder_date_end_final().plusDays(1));
            item.put("end_date_continue", entity.endDate(true).plusDays(1));
        }

        getR().put("list", list);

        return getR();
    }

    /**
     * 申请退款
     */
    @PostMapping("refund_apply")
    public XReturn refundApply(@Validated VoBookOrderRefundApply vo, BindingResult result) {
        //
        XValidator.getResult(result, true, true);

        return SvcBookOrder.getBean().refundApply(vo);
    }

    /**
     * 退款详情
     */
    @PostMapping("refund_info")
    public XReturn refundInfo() {
        String refundId = input("refund_id");
        XValidator.isNullOrEmpty(refundId, "miss refund_id");

        BookRefundOrder entityRefund = BookRefundOrderService.getBean().getEntity(refundId);
        XValidator.isNull(entityRefund, "退款订单异常");

        Map<String, Object> mapRefund = XBean.toMap(entityRefund, new String[]{
                "brefo_id",
                "brefo_price",
                "brefo_audit_status",
                "brefo_audit_status_date",
                "brefo_audit_desc",
                "brefo_refund_id",
                "brefo_refund_price",
                "brefo_refund_handle",
                "brefo_refund_handle_date",
                "brefo_refund_errmsg",
        });

        getR().put("refund", mapRefund);

        return getR();
    }

    /**
     * 加积分
     */
    @GetMapping("add_fun")
    public XReturn addFun() {
        String desc = input("desc");
        XValidator.isNullOrEmpty(desc, "缺少描述");

        String key = getUid();
        FunRecord entityByKey = SvcFun.getBean().getEntityByKey(key);
        if (entityByKey == null) {
            Integer num = 100;
            VaFunAdd vaFunAdd = VaFunAdd.of(key
                    , getUid()
                    , "app_book"
                    , "app_book"
                    , num
                    , desc);
            vaFunAdd.setUpdate_fun(true);
            SvcFun.getBean().add(vaFunAdd);
        }

        return getR();
    }


    /**
     * 续单
     *
     * @param vo
     * @param result
     * @return
     */
    @RequestLimit(key = RequestLimitAppBook.class, second = 2)
    @PostMapping("order_continue")
    public XReturn orderContinue(@Validated @RequestBody VoBookOrderContinue vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);
        //
        BookOrder entityOrder = SvcBookOrder.getApp().getEntity(vo.getOrder_id());
        XValidator.isNull(entityOrder, "订单号异常");
        if (!entityOrder.getBorder_uid().equals(getUid())) {
            return XReturn.getR(20197, "非本人订单，不能操作");
        }
        vo.setSale_uid(null);
        return SvcBookOrder.getBean().orderContinue(vo);
    }
}


